import dgram from 'dgram'
import Emitter from '@multi-kit/emitter'

export default class UDPServer extends Emitter {
  constructor({
    port,
    host,
    localPort,
    msgDispatcher
  }) {
    super()
    this.port = port
    this.host = host
    this.localPort = localPort
    this.msgDispatcher = msgDispatcher
    this.socket = dgram.createSocket('udp4')

    this.socket.on('error', (err) => {
      console.error(`UDP 错误: ${err.message}`)
      this.socket.close()
    })

    this.socket.on('message', (msg, rinfo) => {

      const result = msgDispatcher(msg)
      if (!result) {
        return
      }

      const { header, cmd, identify, length, data, bcc } = result;
      // console.log('message-------------->',result )
      this._events[`message:${cmd}`]?.forEach((event) => {
        event(data, rinfo)
      })

    })

    this.socket.bind(this.localPort, () => {
      this.socket.setBroadcast(true);
      console.log(`UDPServer listening on ${this.localPort}`)
    })
  }

  /**
   * 发送数据包
   * @param {Buffer|string} data - 要发送的数据
   */
  send(data) {
    return new Promise((resolve, reject) => {
      if (typeof data === 'string') {
        data = Buffer.from(data)
      }
      this.socket.send(data, this.port, this.host, (err) => {
        if (err) {
          console.error('UDP 发送错误:', err.message)
          reject(err)
        } else {
          resolve()
        }
      })


    })

  }

  sendAsync(cmd, buffer, { parser }) {
    let hasAccept = false
    return new Promise((resolve, reject) => {
      if (typeof buffer === 'string') {
        buffer = Buffer.from(buffer)
      }
      const onMessage = (msg, rinfo) => {
        const message = parser(msg, rinfo)
        // console.log('msg', msg)
        hasAccept = true
        this.off(`message:${cmd}`, onMessage)
        resolve(message)
        // if (acceptChecker(message)) {

        // }
      }
      this.on(`message:${cmd}`, onMessage)
      const timer = setTimeout(() => {
        if (!hasAccept) {
          this.off(`message:${cmd}`, onMessage)
          reject(new Error('Timeout waiting for response'))
        }
        clearTimeout(timer)
      }, 700)
      this.socket.send(buffer, this.port, this.host)
    })
  }

  close() {
    // 安全关闭 socket
    this._events = null
    if (this.socket) {
      this.socket.close()
    }
  }
}
